home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Lib / util / str2arg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  4.9 KB  |  207 lines

  1. /* str2arg.c: convert a string into a list of args with 
  2.     key = value processing */
  3.  
  4. # ifndef lint
  5. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Lib/util/RCS/str2arg.c,v 6.0 1991/12/18 20:25:18 jpo Rel $";
  6. # endif
  7.  
  8. /*
  9.  * $Header: /xtel/pp/pp-beta/Lib/util/RCS/str2arg.c,v 6.0 1991/12/18 20:25:18 jpo Rel $
  10.  *
  11.  * $Log: str2arg.c,v $
  12.  * Revision 6.0  1991/12/18  20:25:18  jpo
  13.  * Release 6.0
  14.  *
  15.  */
  16.  
  17.  
  18.  
  19. #include "util.h"
  20.  
  21. /*  convert string into argument list
  22.  *
  23.  *  stash a pointer to each field into the passed array.
  24.  *  any common seperators split the words.  extra white-space
  25.  *  between fields is ignored.
  26.  *
  27.  *  if the separator is '=', then the current argument position in
  28.  *  the array points to "=", the next the one is the key and the
  29.  *  value follows it.  This permits detecting variable assignment,
  30.  *  in addition to positional arguments.
  31.  *      i.e.,  key=value ->  = key value
  32.  *
  33.  *  specially-interpreted characters:
  34.  *      space, tab, double-quote, backslash, comma, equal, slash, period,
  35.  *      semi-colon, colon, carriage return, and line-feed (newline).
  36.  *      preceding a special char with a backslash removes its
  37.  *      interpretation.  a backslash not followed by a special is used
  38.  *      to preface an octal specification for one character
  39.  *
  40.  *      a string begun with double-quote has only double-quote and
  41.  *      backslash as special characters.
  42.  *
  43.  *  a field which begins with a hash (#) is interpreted
  44.  *  as marking the rest of the line as a comment and it is skipped, as
  45.  *  are blank lines
  46.  */
  47.  
  48. extern int errno;
  49.  
  50. int str2arg (srcptr, maxf, argv)/* convert srcptr to argument list */
  51.     register char *srcptr;  /* source data */
  52.     int maxf;                /* maximum number of permitted fields */
  53.     char *argv[];           /* where to put the pointers */
  54. {
  55.     char gotquote;      /* currently parsing quoted string */
  56.     char lastdlm;       /* last delimeter character     */
  57.     register int ind;
  58.     register char *destptr;
  59.  
  60.     if (srcptr == 0)
  61.     {
  62.     errno = EINVAL;     /* emulate system-call failure */
  63.     return (NOTOK);
  64.     }
  65.  
  66.     for (lastdlm = (char) NOTOK, ind = 0, maxf -= 2; *srcptr != '\0'; ind++)
  67.     {
  68.     if (ind >= maxf)
  69.     {
  70.         errno = E2BIG;      /* emulate system-call failure */
  71.         return (NOTOK);
  72.     }
  73.     for (argv[ind] = destptr = srcptr; isspace (*srcptr); srcptr++)
  74.         ;               /* skip leading white space         */
  75. /* */
  76.  
  77.     for (gotquote = FALSE; ; )
  78.     {
  79.         switch (*srcptr)
  80.         {
  81.         default:        /* just copy it                     */
  82.             *destptr++ = *srcptr++;
  83.             break;
  84.  
  85.         case '\"':      /* beginning or end of string       */
  86.         case '\'':
  87.             if (gotquote && gotquote == *srcptr)
  88.                 gotquote = FALSE;
  89.             else if (gotquote)
  90.                 *destptr ++ = *srcptr;
  91.             else
  92.                 gotquote = *srcptr;
  93.             srcptr++;
  94.             break;
  95.  
  96.         case '\\':      /* quote next character             */
  97.             srcptr++;   /* just skip the back-slash         */
  98.             switch (*srcptr)
  99.             {           /* convert octal values             */
  100.             case 'r':
  101.                 *destptr++ = '\r';
  102.                 srcptr++;
  103.                 break;
  104.  
  105.             case 'n':
  106.                 *destptr++ = '\n';
  107.                 srcptr++;
  108.                 break;
  109.  
  110.             case 'b':
  111.                 *destptr++ = '\b';
  112.                 srcptr++;
  113.                 break;
  114.  
  115.             case 'f':
  116.                 *destptr++ = '\f';
  117.                 srcptr++;
  118.                 break;
  119.  
  120.             default:
  121.                 if (*srcptr >= '0' && *srcptr <= '7')
  122.                 {
  123.                 *destptr = '\0';
  124.                 do
  125.                     *destptr = (*destptr << 3) | (*srcptr++ - '0');
  126.                 while (*srcptr >= '0' && *srcptr <= '7');
  127.                 destptr++;
  128.                 break;
  129.                 }    /* otherwise DROP ON THROUGH */
  130.             case '\\':
  131.             case '\"':
  132.             case ' ':
  133.             case ',':
  134.             case '\t':
  135.             case ';':
  136.             case '#':
  137.             case ':':
  138.             case '=':
  139.             case '/':
  140.             case '|':
  141.                 *destptr++ = *srcptr++;
  142.                 break; /* just copy it */
  143.             }       /* DROP ON THROUGH */
  144.             break;
  145.  
  146.         case '=':   /* make '=' prefix to pair  */
  147.             if (gotquote)
  148.             {
  149.             *destptr++ = *srcptr++;
  150.             break;
  151.             }
  152.  
  153.             ind++;      /* put value ahead of '=' */
  154.  
  155.             argv[ind] = argv[ind - 1];
  156.             lastdlm = '=';
  157.             argv[ind - 1] = "=";
  158.             *destptr = '\0';
  159.             srcptr++;
  160.             goto nextarg;
  161.  
  162.         case ' ':
  163.         case '\t':
  164.         case '\n':
  165.         case '\r':
  166.         case ',':
  167.         case ';':
  168.         case '#':
  169.         case ':':
  170.         case '/':
  171.         case '|':
  172.             if (gotquote)
  173.             {           /* don't interpret the char */
  174.             *destptr++ = *srcptr++;
  175.             break;
  176.             }
  177.  
  178.             if (isspace (lastdlm))
  179.             {
  180.             if (isspace (*srcptr))
  181.             {           /* shouldn't be possible */
  182.                 errno = EINVAL;
  183.                 return (NOTOK);
  184.             }
  185.             else
  186.                 if (*srcptr != '#')
  187.                 ind--;  /* "xxx , yyy" is only 2 fields */
  188.             }
  189.             lastdlm = *srcptr;
  190.             srcptr++;
  191.         case '\0':
  192.             *destptr = '\0';
  193.             goto nextarg;
  194.         }
  195.  
  196.         lastdlm = (char) NOTOK;     /* disable when field started */
  197.     }
  198.  
  199.     nextarg:
  200.     if (argv[ind][0] == '\0' && lastdlm == '#')
  201.         break;      /* rest of line is comment                  */
  202.     }
  203.  
  204.     argv[ind] = (char *) 0;
  205.     return (ind);
  206. }
  207.